package com.lmk.user.service.impl;

import com.lmk.basic.exception.BusinessException;
import com.lmk.basic.service.Impl.BaseServiceImpl;
import com.lmk.basic.util.Md5Utils;
import com.lmk.basic.util.StrUtils;
import com.lmk.user.domain.Logininfo;
import com.lmk.user.domain.User;
import com.lmk.user.dto.UserDto;
import com.lmk.user.mapper.LogininfoMapper;
import com.lmk.user.mapper.UserMapper;
import com.lmk.user.service.IUserService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;

/**
 * 业务实现类：
 */
@Service
public class UserServiceImpl extends BaseServiceImpl<User> implements IUserService {
    @Autowired
    private JavaMailSender javaMailSender;

    @Autowired
    private RedisTemplate redisTemplate;


    @Autowired
    private UserMapper userMapper;

    @Autowired
    private LogininfoMapper logininfoMapper;

    @Override
    @Transactional
    public void phoneRegister(UserDto userDto) {
        // 1.空值校验
        String phone = userDto.getPhone();
        String phoneCode = userDto.getPhoneCode();
        String pwd = userDto.getPwd();
        String confirmPwd = userDto.getConfirmPwd();
        if ((StringUtils.isEmpty(phone) || StringUtils.isEmpty(phoneCode) ||
                StringUtils.isEmpty(pwd) || StringUtils.isEmpty(confirmPwd))) {
            throw new BusinessException("数据不能为空");
        }
        //判断密码是否相等
        if(!pwd.equals(confirmPwd)){
            throw new BusinessException("两次密码不相等");
        }
        //判断验证码是否过期
        Object codeObj = redisTemplate.opsForValue().get("register"+phone);
        if(codeObj== null){
            throw new BusinessException("手机验证码已过期，请点击重新发送验证码");
        }
        //判断手机验证码是否正确
        String s = codeObj.toString().split(":")[0];
        if(!s.equals(phoneCode)){
            throw new BusinessException("手机验证码错误");
        }

        // 对象转换
        User user = userDto2User(userDto);
        Logininfo logininfo = user2Logininfo(user);

        // 保存logininfo
        logininfoMapper.save(logininfo);

        // 保存user
        user.setLogininfoId(logininfo.getId());
        userMapper.save(user);

    }
    //邮箱注册
    @Override
    @Transactional
    public void emailRegister(UserDto userDto) {
        // 校验判断传入数据是否为空
        String email = userDto.getEmail();
        String pwd = userDto.getPwd();
        String confirmPwd = userDto.getConfirmPwd();
        if (StringUtils.isEmpty(email) || StringUtils.isEmpty(pwd)
                || StringUtils.isEmpty(confirmPwd)) {
            throw new BusinessException("邮箱或密码不能为空");
        }
        // 判断输入的两次密码是否相同
        if(!pwd.equals(confirmPwd)){
            throw new BusinessException("两次密码不相等");
        }
        //判断邮箱是否已经被注册
        User user = userMapper.loadByEmail(email);
        if(user!=null){
            throw new BusinessException("该邮箱已已经注册过了，请直接登录");
        }
        try {
            //发送邮件
            MimeMessage mimeMessage = javaMailSender.createMimeMessage();
            //工具类
            MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true, "UTF-8");
            //发送人
            helper.setFrom("1767442215@qq.com");
            //接收人
            helper.setTo(userDto.getEmail());
            //标题
            helper.setSubject("注册成功");
            //内容
            helper.setText("<h1>恭喜！注册成功啦</h1><h3>" +
                    "<a href='http://localhost/login.html'>点击该链接进入到登录</a></h3>", true);
            //发送
            javaMailSender.send(mimeMessage);
        } catch (MessagingException e) {
            e.printStackTrace();
            throw new BusinessException("邮件发送失败");
        }
        User user1 = userDto3User(userDto);
        Logininfo logininfo = user2Logininfo(user1);
        //先保存logininfo
        logininfoMapper.save(logininfo);

        //在保存user
        user1.setLogininfoId(logininfo.getId());
        userMapper.save(user1);


    }
    private Logininfo user2Logininfo(User user) {
        Logininfo logininfo = new Logininfo();
        //按照同名属性赋值【username，email，phone，salt，password】
        BeanUtils.copyProperties(user,logininfo);
        //设置type
        logininfo.setType(1);
        logininfo.setDisable(true);
        return logininfo;

    }

    private User userDto2User(UserDto userDto) {
        User user = new User();
        user.setUsername(userDto.getPhone());
        user.setPhone(userDto.getPhone());
        //获取32盐值
        String salt = StrUtils.getComplexRandomString(32);
        user.setSalt(salt);
        // 密码加密加盐，并获取加密加盐的密码
        String md5Pwd = Md5Utils.encrypByMd5(userDto.getPwd() + salt);
        // 设置密码
        user.setPassword(md5Pwd);
        return user;
    }
    private User userDto3User(UserDto userDto) {
        User user = new User();
        user.setUsername(userDto.getEmail());
        user.setEmail(userDto.getEmail());
        //获取32盐值
        String salt = StrUtils.getComplexRandomString(32);
        user.setSalt(salt);
        String md5Pwd = Md5Utils.encrypByMd5(userDto.getPwd() + salt);
        user.setPassword(md5Pwd);
        return user;
    }

    @Override
    @Transactional
    public void add(User user) {
        //1.处理密码和盐值
        //获取随机盐值
        String salt = StrUtils.getComplexRandomString(32);
        //获取加密之后的密码
        String md5Pwd = Md5Utils.encrypByMd5(user.getPassword()+salt);
        user.setSalt(salt);
        user.setPassword(md5Pwd);
        // 保存logininfo
        Logininfo logininfo = user2Logininfo(user);
        logininfoMapper.save(logininfo);

        super.add(user);
    }

    @Override
    @Transactional
    public void update(User user) {
        //1.处理密码和盐值
        //获取随机盐值
        String salt = StrUtils.getComplexRandomString(32);
        //获取加密之后的密码
        String md5Pwd = Md5Utils.encrypByMd5(user.getPassword()+salt);
        user.setSalt(salt);
        user.setPassword(md5Pwd);

        //获取登录信息id
        Long logininfo_id = userMapper.loadById(user.getId()).getLogininfoId();
        //登录信息logininfo：type不修改
        Logininfo logininfo = user2Logininfo(user);
        logininfo.setId(logininfo_id);

        logininfoMapper.update(logininfo);

        super.update(user);
    }

    @Override
    @Transactional
    public void del(Long id) {
        //获取登录信息id
        Long logininfo_id = userMapper.loadById(id).getLogininfoId();
        //删除登录信息对象
        logininfoMapper.remove(id);

        super.del(id);
    }
}
